package com.pcbly.web.components.utils.fileupload;

import java.io.BufferedReader;
import java.io.File;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.HashMap;
import java.util.Map;
import java.util.Properties;

import javax.servlet.http.HttpServletRequest;

import org.apache.commons.fileupload.FileItem;
import org.apache.commons.fileupload.FileItemFactory;
import org.apache.commons.fileupload.FileItemIterator;
import org.apache.commons.fileupload.FileItemStream;
import org.apache.commons.fileupload.FileUploadException;
import org.apache.commons.fileupload.disk.DiskFileItemFactory;
import org.apache.commons.fileupload.servlet.ServletFileUpload;
import org.apache.commons.fileupload.util.Streams;
import org.apache.log4j.Logger;

import com.pcbly.web.Constants;



/**
 * 工具类
 * @author cleverpig
 *
 */
public class Utils {
	private static Logger logger=Logger.getLogger(Utils.class);
	//非元音字母
	private static char NON_VOWELS[] = {'b', 'c', 'd', 'f', 'g', 'h', 'j', 'k', 'l', 'm', 'n', 'p', 'q', 'r', 's', 't', 'v', 'w', 'z'};
	//元音字母
	private static char VOWELS[] = {'a', 'e', 'i', 'o', 'u', 'y'};
	
	/**
	 * 生成随机整数
	 * @param min
	 * @param max
	 * @return
	 */
	public static int randomInt(int min, int max) {
		return (int) ((Math.random() * (double) (max + 1 - min)) + min);
	}
	
	/**
	 * 生成随机元音字母
	 * @return
	 */
	public static char randomVowel() {
		return VOWELS[randomInt(0, VOWELS.length - 1)];
	}
	/**
	 * 生成随机非元音字母
	 * @return
	 */
	public static char randomNonVowel() {
		return NON_VOWELS[randomInt(0, NON_VOWELS.length - 1)];
	}
	/**
	 * 生成非元音/元音交错的字串
	 * @param aLength
	 * @return
	 */
	public static String randomName(int aLength) {
		StringBuffer sb = new StringBuffer(aLength);
		for (int i = 0; i < aLength; i++) {
			sb.append(i % 2 == 0 ? randomNonVowel() : randomVowel());
		}
		return sb.toString();
	}
	
	/**
	 * 从httpRequest中取出sessionId
	 * @param request
	 * @return
	 */
	public static String getSessionIdFromHttpRequest(HttpServletRequest request){
		String sessionId=request.getParameter(Constants.SESSION_KEY);
		logger.debug("从httpRequest中取出sessionId："+sessionId);
		return sessionId;
	}
	
	/**
	 * 从httpRequest中取出forwardURL
	 * @param request
	 * @return
	 */
	public static String getForwardURLFromHttpRequest(HttpServletRequest request){
		String forwardURL=request.getParameter(Constants.FORWARDURL_KEY);
		logger.debug("从httpRequest中取出forwardURL："+forwardURL);
		return forwardURL;
	}
	
	/**
	 * 从multiPart-httpRequest中取出参数Map
	 * @param request
	 * @param ServletFileUpload
	 * @return
	 * @throws IOException 
	 */
	public static Map<String,String> getParametersMapFromMultiPartHttpRequest(
			HttpServletRequest request,ServletFileUpload servletFileUpload) throws IOException{
		Map<String,String> paramMap=new HashMap<String,String>();
		try {
			FileItemIterator iter=servletFileUpload.getItemIterator(request);
			FileItemFactory fac = servletFileUpload.getFileItemFactory();
			while(iter.hasNext()){
				FileItemStream item=iter.next();
				logger.debug("在MultiPart-httpRequest中发现field["+item.getFieldName()+"]");
				if (item.isFormField()){
					FileItem fileItem=fac.createItem(item.getFieldName(),
	                        item.getContentType(), item.isFormField(),
	                        item.getName());
		            Streams.copy(item.openStream(), fileItem.getOutputStream(), true);
					logger.debug("从MultiPart-httpRequest中取出"+fileItem.getFieldName()+"："+fileItem.getString());
					paramMap.put(fileItem.getFieldName(), fileItem.getString());
				}
			}
		} catch (FileUploadException e) {
			logger.error("解析MultiPart-httpRequest时发生错误:"+e.getMessage());
			e.printStackTrace();
		} catch (IOException e) {
			logger.error("解析MultiPart-httpRequest时发生IO错误:"+e.getMessage());
			e.printStackTrace();
		}
		request.getInputStream().reset();
		return paramMap;
	}
	
	/**
	 * 从multiPart-httpRequest中取出参数Map
	 * @param request
	 * @return
	 * @throws IOException 
	 */
	public static Map<String,String> getParametersMapFromMultiPartHttpRequest(
			HttpServletRequest request) throws IOException{
		ServletFileUpload servletFileUpload = new ServletFileUpload(new DiskFileItemFactory());
		return getParametersMapFromMultiPartHttpRequest(request,servletFileUpload);
	}
	
	/**
	 * 从文件路径中取出文件名
	 * @param filePath
	 * @return
	 */
	public static String takeOutFileName(String filePath){
		int pos=filePath.lastIndexOf(File.separator);
		if (pos>0){
			return filePath.substring(pos+1);
		}
		else{
			return filePath;
		}
	}
	/**
	 * 执行本地程序
	 * @param cmd 命令参数
	 * @param baseDir 工作目录
	 * @return 返回程序输出
	 */
	public static StringBuffer runNativeProgram(String cmd[],String baseDir){
		Process p;
		try {
			p = Runtime.getRuntime().exec(cmd,null,new File(baseDir));
			BufferedReader in = new BufferedReader( new InputStreamReader(p.getInputStream()));
			
			StringBuffer normalSB = new StringBuffer();
			String currentLine=null;
			while ((currentLine = in.readLine()) != null ){
				normalSB.append(currentLine);
				normalSB.append("\n");
			}

			BufferedReader err=new BufferedReader(new InputStreamReader(p.getErrorStream()));
			StringBuffer errorSB = new StringBuffer();
			while ((currentLine = err.readLine()) != null ){
				errorSB.append(currentLine);
				errorSB.append("\n");
			}
//			等待进程结束

			p.waitFor();
//			System.out.println("Exited with error code:"+exitVal);
//			System.out.println("error code:"+errorSB);
			in.close();
			err.close();
			return normalSB;
		} catch (IOException e) {
			e.printStackTrace();
			logger.debug("执行病毒扫描程序时发生错误:"+e.getMessage());
			return null;
		} catch (InterruptedException e) {
			e.printStackTrace();
			return null;
		}
	}
	/**
	 * 调用ClamAV进行病毒扫描
	 * @param scanFilePath 等待扫描文件的路径
	 * @return 文件没有被感染/读取配置文件失败/待扫描文件不存在/配置文件中查毒使能项为false 返回true
	 */
	public static boolean scanInfectedFileWithCallClamAV(String scanFilePath){
		Properties props=new Properties();
		Logger logger=Logger.getLogger(Utils.class);
		
		try {
			props.load(Utils.class.getResourceAsStream("/clamscan.properties"));
		} catch (IOException e) {
			logger.debug("读取配置文件失败:"+e.getMessage());
			return true;
		}
		String enableFlag=props.getProperty("enable");
		if (enableFlag.equalsIgnoreCase("false")){
			logger.debug("配置文件中查毒失效");
			return true;
		}
		else{
			File file=new File(scanFilePath);
			if (!file.isFile()){
				logger.debug("待扫描文件不存在!");
				return true;
			}
			String[] cmd=new String[2];
			cmd[0]=props.getProperty("executeFile");
			cmd[1]=scanFilePath;
			StringBuffer sb=runNativeProgram(cmd,props.getProperty("libPath"));
			logger.debug("扫描输出:\n"+sb);
			if (sb==null){
				return false;
			}
			else{
				return sb.toString().indexOf("Infected files: 0")>=0?true:false;
			}
		}
	}
}
